1520c8
@@ -63,6 +63,7 @@
class SimpleServerRpcConnection extends ServerRpcConnection {
   final SocketChannel channel;
   private ByteBuff data;
   private ByteBuffer dataLengthBuffer;
+  private ByteBuffer preambleBuffer;
   protected final ConcurrentLinkedDeque<SimpleServerCall> responseQueue =
       new ConcurrentLinkedDeque<>();
   final Lock responseWriteLock = new ReentrantLock();
@@ -130,22 +131,25 @@
class SimpleServerRpcConnection extends ServerRpcConnection {
   }
 
   private int readPreamble() throws IOException {
-    int count;
-    // Check for 'HBas' magic.
-    this.dataLengthBuffer.flip();
-    if (!Arrays.equals(HConstants.RPC_HEADER, dataLengthBuffer.array())) {
-      return doBadPreambleHandling(
-        "Expected HEADER=" + Bytes.toStringBinary(HConstants.RPC_HEADER) + " but received HEADER=" +
-            Bytes.toStringBinary(dataLengthBuffer.array()) + " from " + toString());
+    if (preambleBuffer == null) {
+      preambleBuffer = ByteBuffer.allocate(6);
     }
-    // Now read the next two bytes, the version and the auth to use.
-    ByteBuffer versionAndAuthBytes = ByteBuffer.allocate(2);
-    count = this.rpcServer.channelRead(channel, versionAndAuthBytes);
-    if (count < 0 || versionAndAuthBytes.remaining() > 0) {
+    int count = this.rpcServer.channelRead(channel, preambleBuffer);
+    if (count < 0 || preambleBuffer.remaining() > 0) {
       return count;
     }
-    int version = versionAndAuthBytes.get(0);
-    byte authbyte = versionAndAuthBytes.get(1);
+    // Check for 'HBas' magic.
+    preambleBuffer.flip();
+    for (int i = 0; i < HConstants.RPC_HEADER.length; i++) {
+      if (HConstants.RPC_HEADER[i] != preambleBuffer.get(i)) {
+        return doBadPreambleHandling("Expected HEADER=" +
+            Bytes.toStringBinary(HConstants.RPC_HEADER) + " but received HEADER=" +
+            Bytes.toStringBinary(preambleBuffer.array(), 0, HConstants.RPC_HEADER.length) +
+            " from " + toString());
+      }
+    }
+    int version = preambleBuffer.get(HConstants.RPC_HEADER.length);
+    byte authbyte = preambleBuffer.get(HConstants.RPC_HEADER.length + 1);
     this.authMethod = AuthMethod.valueOf(authbyte);
     if (version != SimpleRpcServer.CURRENT_VERSION) {
       String msg = getFatalConnectionString(version, authbyte);
@@ -178,8 +182,7 @@
class SimpleServerRpcConnection extends ServerRpcConnection {
     if (authMethod != AuthMethod.SIMPLE) {
       useSasl = true;
     }
-
-    dataLengthBuffer.clear();
+    preambleBuffer = null; // do not need it anymore
     connectionPreambleRead = true;
     return count;
   }
@@ -200,26 +203,19 @@
class SimpleServerRpcConnection extends ServerRpcConnection {
    * @throws InterruptedException
    */
   public int readAndProcess() throws IOException, InterruptedException {
-    // Try and read in an int. If new connection, the int will hold the 'HBas' HEADER. If it
-    // does, read in the rest of the connection preamble, the version and the auth method.
-    // Else it will be length of the data to read (or -1 if a ping). We catch the integer
-    // length into the 4-byte this.dataLengthBuffer.
-    int count = read4Bytes();
-    if (count < 0 || dataLengthBuffer.remaining() > 0) {
-      return count;
-    }
-
     // If we have not read the connection setup preamble, look to see if that is on the wire.
     if (!connectionPreambleRead) {
-      count = readPreamble();
+      int count = readPreamble();
       if (!connectionPreambleRead) {
         return count;
       }
+    }
 
-      count = read4Bytes();
-      if (count < 0 || dataLengthBuffer.remaining() > 0) {
-        return count;
-      }
+    // Try and read in an int. it will be length of the data to read (or -1 if a ping). We catch the
+    // integer length into the 4-byte this.dataLengthBuffer.
+    int count = read4Bytes();
+    if (count < 0 || dataLengthBuffer.remaining() > 0) {
+      return count;
     }
 
     // We have read a length and we have read the preamble. It is either the connection header
